// This file is part of MinIO Console Server
// Copyright (c) 2019 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

import React from "react";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import api from "../../../common/api";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import FormControl from '@material-ui/core/FormControl';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import InputBase from '@material-ui/core/InputBase';
import { LinearProgress } from "@material-ui/core";
import { ChartUrl, beforeNowtimeBySec } from "./types";
import Alert from '@material-ui/lab/Alert';
import NodeCPU from "./NodeCPU";
import NodeCPUio from "./NodeCPUio";
import NodeCPUUser from "./NodeCPUUser";
import NodeDisk from "./NodeDisk";
import NodeMem from "./NodeMem";
import NodeDiskFree from "./NodeDiskFree";
import NodeReadWrite from "./NodeReadWrite";
import NodeNetTransRate from "./NodeNetTransRate";

const BootstrapInput = withStyles((theme: Theme) =>
  createStyles({
    root: {
      'label + &': {
        marginTop: 0,
        paddingLeft: theme.spacing(4),
      },
    },
    input: {
      borderRadius: 4,
      position: 'relative',
      backgroundColor: theme.palette.background.paper,
      border: '1px solid #ced4da',
      fontSize: 14,
      padding: '5px 26px 5px 12px',
      transition: theme.transitions.create(['border-color', 'box-shadow']),
      '&:focus': {
        borderRadius: 4,
        borderColor: '#80bdff',
        boxShadow: '0 0 0 0.2rem rgba(0,123,255,.25)',
      },
    },
  }),
  )(InputBase);
const styles = (theme: Theme) =>
  createStyles({
    itemTitle: {
      textAlign: "center",
    },
    selItem: {
      margin:"15px 0",
      width: "100%",
      flexDirection: "row"
    },
    selNode: {
      whiteSpace: "nowrap",
      lineHeight: "31px"
    },
    container: {
      marginTop: theme.spacing(12),
      paddingBottom: theme.spacing(4),
    },
    h6: {
      color: "#777777",
      fontSize: 14,
      fontWeight:"normal"
    },
    paper: {
      padding: theme.spacing(1),
      display: "flex",
      overflow: "auto",
      flexDirection: "column",
    },
    nodetitle: {
      position: "absolute",
      top: "0",
      left: "0",
      width: "100%",
      height: "77px",
      lineHeight: "77px",
      justifyContent: "space-between",
      background: "#fff",
      borderBottom: "1px solid #e3e3e3"
    },
    nodeh4: {
      marginLeft: "55px",
      lineHeight: "77px",
      color: "#000",
      fontSize: "18px",
      fontWeight: 700
    },
    serve: {
      width:"100%",
      padding: theme.spacing(1),
      paddingTop: theme.spacing(2),
      background: "#fff",
      borderRadius:"3px",
    },
    serveItem: {
      padding: theme.spacing(1),
      boxShadow: "none"
    },
    serveTitle: {
      marginLeft: theme.spacing(1),
      marginRight: theme.spacing(1),
      paddingLeft: theme.spacing(2),
      color: theme.palette.primary.main,
      fontSize: 14,
      borderLeft: "4px solid",
      borderColor: theme.palette.warning.main
    },
    over: {
      padding: theme.spacing(1),
    },
    overChart: {
      minHeight: 230,
      padding: 8,
      border: "1px solid #ddd",
      borderRadius: 5,
      background: "#efefef",
      overflow:"hidden"
    },
    linear: {
      padding: "12px 0"
    }
});
interface INodeProps {
  classes: any;
}

// const NodeExporter = ({ classes }: INodeProps) => {
export class NodeExporter extends React.Component<INodeProps, any> {
  constructor(props:any){
    super(props);
    this.state = {
      loading: true,
      errinfo:"",
      node: "",
      instance:[],
    };
  };

  componentDidMount(): void {
    this.initialQuery()
  }
  // getSnapshotBeforeUpdate(): void {
  //   this.set()
  // }
  // set () {
  //   console.log(this.state.node)
  //   this.setState({
  //     node: this.state.node
  //   })
  // }
  initialQuery () {
    var arr = new Array;
    let url = ChartUrl+"sum(increase(node_cpu_seconds_total{mode='idle'}[1m]))by(instance)&start="+Date.parse(beforeNowtimeBySec(2000)).toString().substring(0,10)+"&end="+Date.parse(beforeNowtimeBySec(0)).toString().substring(0,10)+"&step=1";
    // let url = ChartUrl+"scrape_duration_seconds&start="+Date.parse(beforeNowtimeBySec(1)).toString().substring(0,10)+"&end="+Date.parse(beforeNowtimeBySec(0)).toString().substring(0,10)+"&step=1";
    api
      .invoke("GET", url)
      .then((res) => {
        var rootData = res.data.result;
        if(rootData != []){
          for(var i=0;i<rootData.length;i++){
            arr.push(rootData[i].metric.instance)
          }
          this.setState({
            instance:arr,
            errinfo:"",
            loading:false
          })
        }else{
          this.setState({
            errinfo:"暂无数据",
            loading:true
          })
        }
      })
      .catch((err) => {
        this.setState({
          errinfo:err,
          loading:true
        })
      });
  };
  
render() {
  const { classes } = this.props;
  var handleChangeQueryUrl = (event: React.ChangeEvent<{ value: unknown }>) => {
    console.log(event.target.value)
    this.setState({ 
      node: event.target.value
    });

  };
  return (
    <React.Fragment>
      <Grid container className={classes.nodetitle}>
        <Typography variant="h4" className={classes.nodeh4}>Node Exporter</Typography>
      </Grid>
      <Grid container className={classes.container}>
        {this.state.error !== "" && <Grid container>{this.state.errorinfo}</Grid>}
        {this.state.loading ? (
          <Grid item xs={12} md={12} lg={12} className={classes.linear}>
            <LinearProgress />
          </Grid>
        ) : (
          <React.Fragment>
            
            <Grid container>
              <FormControl className={classes.selItem}>
                <Typography className={classes.selNode}>选择节点：</Typography>
                <Select
                  labelId="instance"
                  id="instanceSel"
                  value={this.state.node}
                  onChange={handleChangeQueryUrl}
                  input={<BootstrapInput />}
                  style={{width: "200px"}}
                >
                  {this.state.instance.map((node:string) => {
                    return(
                      <MenuItem value={node}>{node}</MenuItem>
                    )
                  })}
                </Select>
                <span>{this.state.errinfo}</span>
              </FormControl>
            </Grid>
            {this.state.instance == "" &&
              <Alert severity="error" style={{width:"280px",padding: "0 16px"}}>
                暂无数据
              </Alert>
            }
            
            {/* {this.state.node != "" && */}
            <Grid container>
              <Paper className={classes.serve}>
                <Grid container style={{justifyContent: "space-between"}}>
                  <Typography variant="subtitle1" className={classes.serveTitle}>节点监控数据</Typography>
                </Grid>
                <Grid container>
                  <Grid item  style={{width:"20%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>CPU使用率（1m）</Typography>
                      </Grid>
                      <NodeCPU inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"20%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>CPU iowait（1m）</Typography>
                      </Grid>
                      <NodeCPUio inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"20%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>CPU user（1m）</Typography>
                      </Grid>
                      <NodeCPUUser inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"20%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>内存使用率</Typography>
                      </Grid>
                      <NodeMem inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"20%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>根分区使用率</Typography>
                      </Grid>
                      <NodeDisk inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"20%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>硬盘剩余空间</Typography>
                      </Grid>
                      <NodeDiskFree inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"40%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>磁盘读写I/O（1s）</Typography>
                      </Grid>
                      <NodeReadWrite inputNode={this.state.node}/>
                    </div>
                  </Grid>
                  <Grid item  style={{width:"40%"}} className={classes.over}>
                    <div className={classes.overChart}>
                      <Grid container direction="row" alignItems="center" justify="center">
                        <Typography variant="h6" className={classes.h6}>网络传输速率（1s）</Typography>
                      </Grid>
                      <NodeNetTransRate inputNode={this.state.node}/>
                    </div>
                  </Grid>
                </Grid>
              </Paper>
            </Grid>
            {/* } */}
          </React.Fragment>
        )}
      </Grid>
    </React.Fragment>
  );
};
};

// export default withStyles(styles)(NodeExporter);

const mapDispatchToProps = (dispatch:any) => {
  return {
    beforeNowtimeBySec: (sec:any) => dispatch(beforeNowtimeBySec(sec)),
  }
}
// export default NodeExporter
export default withStyles(styles)(NodeExporter)
// 计算CPU的使用时间
// 空闲CPU使用时间 = node_cpu_seconds_total{mode='idle'}
// CPU总共使用时间 = node_cpu_seconds_total

// CPU 每分钟使用率
// (1-((sum(increase(node_cpu_seconds_total{mode='idle'}[1m]))by(instance))/(sum(increase(node_cpu_seconds_total[1m]))by(instance))))*100

// CPU-system 每分钟使用率
// (sum(increase(node_cpu_seconds_total{mode='system'}[1m]))by(instance))/(sum(increase(node_cpu_seconds_total[1m]))by(instance))*100

// CPU-iowait 每分钟使用率
// (sum(increase(node_cpu_seconds_total{mode='iowait'}[1m]))by(instance))/(sum(increase(node_cpu_seconds_total[1m]))by(instance))*100

// CPU-user 每分钟利用率
// (sum(increase(node_cpu_seconds_total{mode='user'}[1m]))by(instance))/(sum(increase(node_cpu_seconds_total[1m]))by(instance))*100

// 节点内存使用率 (centos7)
// (1-node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)*100

// 硬盘剩余空间百分比
// ((sum(node_filesystem_free_bytes{fstype="xfs"})by(instance))/(sum(node_filesystem_size_bytes{fstype="xfs"})by(instance)))*100

// 网络接收总字节数
// node_network_receive_bytes_total{device="ens33"}

// 网络传输每秒钟速率
// rate(node_network_transmit_bytes_total{device="ens33"}[1m])

// 文件描述符使用率
// (node_filefd_allocated/node_filefd_maximum)*100

// 统计磁盘 1分钟每秒 读写 I/O ，Mb/S
// (rate(node_disk_read_bytes_total{device='sda'}[1m])+rate(node_disk_written_bytes_total{device='sda'}[1m]))/1024/1024

// 磁盘 根分区利用率
// (1-(sum(node_filesystem_free_bytes{fstype='xfs'})by(instance)/sum(node_filesystem_size_bytes{fstype='xfs'})by(instance)))*100

// Gauge 瞬时数据类型 
// 定义：取前几位的最高值。格式：topk(number,key)
// topk(2,node_memory_MemAvailable_bytes)